package com.bjb.vr.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.UmsRoleAo;
import com.bjb.vr.common.constant.RoleConstants;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.constant.UmsMenuConstants;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.UmsMenuMapper;
import com.bjb.vr.common.mapper.UmsRoleMapper;
import com.bjb.vr.common.mapper.UmsRoleMenuMapper;
import com.bjb.vr.common.mapper.UmsUserRoleMapper;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.MenuData;
import com.bjb.vr.common.vo.UmsAccountVo;
import com.bjb.vr.common.vo.UmsMenuVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【ums_menu(菜单权限表)】的数据库操作Service实现
 * @createDate 2022-04-29 11:28:38
 */
@Service
public class UmsMenuService extends ServiceImpl<UmsMenuMapper, UmsMenu> {

    @Autowired
    private UmsMenuMapper umsMenuMapper;

    @Autowired
    private UmsRoleMenuMapper roleMenuMapper;

    @Autowired
    private UmsRoleMapper roleMapper;

    @Autowired
    private UmsUserRoleMapper userRoleMapper;

    /**
     * 查询首页
     *
     * @return
     */
    public List<UmsMenuVo> queryHomePage() {
        List<UmsMenuVo> newMenu = new ArrayList<>();
        // 查询用户信息
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        List<Long> roleIds = userRoleMapper.selectList(new LambdaQueryWrapper<UmsUserRole>().eq(UmsUserRole::getUserId, umsAccountVo.getUserId())).stream().map(UmsUserRole::getRoleId).collect(Collectors.toList());
        // 如果角色为空，说明没有分配角色
        if (CollectionUtils.isEmpty(roleIds)) {
            return newMenu;
        }
        // 判断是不是超级管理员
        List<UmsRole> umsRoles = roleMapper.selectList(new LambdaQueryWrapper<UmsRole>().in(UmsRole::getRoleId, roleIds));
        Map<String, List<UmsRole>> listMap = umsRoles.stream().collect(Collectors.groupingBy(UmsRole::getRoleKey));
        List<MenuData> menusLists = new ArrayList<>();
        if (listMap.containsKey(RoleConstants.SUPER_ADMIN)) {
            menusLists = umsMenuMapper.queryAllMenus();
            // 获取菜单按钮集合
            UmsRole roleInfo = listMap.get(RoleConstants.SUPER_ADMIN).get(0);
            newMenu = getMenuData(menusLists, null, roleInfo);
        } else {
            menusLists = umsMenuMapper.queryHomePage(roleIds, UmsMenuConstants.MANAGER);
            // 获取菜单按钮集合
            newMenu = getMenuData(menusLists, null, null);
        }
        return newMenu;
    }

    /**
     * 查询权限菜单
     *
     * @param umsRoleAo
     * @return
     */
    public List<UmsMenuVo> queryMenus(UmsRoleAo umsRoleAo) {
        // 查询所有菜单列表
        List<MenuData> menusLists = umsMenuMapper.queryAllMenus();
        // 查询角色权限列表
        List<UmsRoleMenu> roleMenus = roleMenuMapper.selectListByRoleId(umsRoleAo.getRoleId(), UmsMenuConstants.MANAGER);
        List<Long> authorizedMenuIds = roleMenus.stream().map(UmsRoleMenu::getMenuId).collect(Collectors.toList());
        UmsRole umsRole = roleMapper.selectById(umsRoleAo.getRoleId());
        // 获取菜单按钮集合
        List<UmsMenuVo> newMenu = getMenuData(menusLists, authorizedMenuIds, umsRole);
        return newMenu;
    }

    /**
     * 获取菜单和按钮
     *
     * @param menusLists
     * @param authorizedMenuIds
     * @param umsRole
     * @return
     */
    private List<UmsMenuVo> getMenuData(List<MenuData> menusLists, List<Long> authorizedMenuIds, UmsRole umsRole) {
        List<MenuData> grandParentMenus = menusLists.stream().collect(Collectors.partitioningBy(menuData -> menuData.getMenuType().equals("M"))).get(true);
        List<MenuData> parentMenus = menusLists.stream().collect(Collectors.partitioningBy(menuData -> menuData.getMenuType().equals("C"))).get(true);
        List<MenuData> childrenMenus = menusLists.stream().collect(Collectors.partitioningBy(menuData -> menuData.getMenuType().equals("F"))).get(true);

        List<UmsMenuVo> newMenu = new ArrayList<>();
        grandParentMenus.stream()
                .forEach(
                        item -> {
                            Long menuId = item.getMenuId();
                            String menuName = item.getMenuName();
                            UmsMenuVo umsMenuVoA = new UmsMenuVo(menuId, menuName);
                            umsMenuVoA.setHasAuthority(item.getHasAuthority());
                            umsMenuVoA.setPerms(item.getPerms());
                            umsMenuVoA.setRouterPath(item.getRouterPath());
                            umsMenuVoA.setIconfont(item.getIconfont());
                            hasPrivilege(umsRole, authorizedMenuIds, umsMenuVoA);

                            // 设置一级菜单
                            List<UmsMenuVo> children =
                                    parentMenus.stream()
                                            .filter(p -> p.getParentId().equals(menuId))
                                            .map(item2 -> {
                                                UmsMenuVo umsMenuVoB =
                                                        new UmsMenuVo(item2.getMenuId(), item2.getMenuName());
                                                umsMenuVoB.setPerms(item2.getPerms());
                                                umsMenuVoB.setHasAuthority(item2.getHasAuthority());
                                                umsMenuVoB.setRouterPath(item2.getRouterPath());
                                                umsMenuVoB.setIconfont(item2.getIconfont());
                                                hasPrivilege(umsRole, authorizedMenuIds, umsMenuVoB);
                                                return umsMenuVoB;
                                            })
                                            .collect(Collectors.toList());

                            // 设置菜单按钮
                            children.stream().forEach(c -> {
                                List<UmsMenuVo> grandChildren =
                                        childrenMenus.stream()
                                                .filter(cc -> cc.getParentId().equals(c.getMenuId()))
                                                .map(item3 -> {
                                                    UmsMenuVo umsMenuVoC = new UmsMenuVo(item3.getMenuId(), item3.getMenuName());
                                                    umsMenuVoC.setHasAuthority(item3.getHasAuthority());
                                                    umsMenuVoC.setPerms(item3.getPerms());
                                                    umsMenuVoC.setRouterPath(item3.getRouterPath());
                                                    umsMenuVoC.setIconfont(item3.getIconfont());
                                                    hasPrivilege(umsRole, authorizedMenuIds, umsMenuVoC);
                                                    return umsMenuVoC;
                                                })
                                                .collect(Collectors.toList());
                                c.setChildrens(grandChildren);
                            });
                            umsMenuVoA.setChildrens(children);
                            newMenu.add(umsMenuVoA);
                        });
        return newMenu;
    }

    /**
     * 设置角色是否有权限
     *
     * @param umsRole
     * @param authorizedMenuIds
     * @param umsMenuVo
     */
    private void hasPrivilege(UmsRole umsRole, List<Long> authorizedMenuIds, UmsMenuVo umsMenuVo) {
        // 判断角色ID是否为空，为空说明新增角色权限
        if (Objects.isNull(umsRole) || Objects.isNull(umsRole.getRoleId())) {
            return;
        }
        // 如果是超级管理员--拥有所有权限
        if (umsRole.getRoleKey().equals(RoleConstants.SUPER_ADMIN)) {
            umsMenuVo.setHasAuthority(1);
            return;
        }
        // 其他角色权限，根据分配的决定
        if (Objects.isNull(authorizedMenuIds) || authorizedMenuIds.size() <= 0) {
            return;
        }
        authorizedMenuIds.stream().forEach(f -> {
            if (f.equals(umsMenuVo.getMenuId())) {
                umsMenuVo.setHasAuthority(1);
            }
        });
    }
}
